package com.zl.learning.thread.forkjoin;

import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.function.DoublePredicate;

/**
 * @author sunrui
 * @version 1.0
 * @date 2020/12/21
 */
public class ForkJoinTest {
    public static void main(String[] args) {
        long start = System.nanoTime();
        double[] array = new double[18000];
        Arrays.parallelSetAll(array, i -> new Random().nextDouble());
        ForkJoinPool pool = new ForkJoinPool(1);
        Counter counter = new Counter(array, 0, array.length, x -> x > 0.5);
        pool.invoke(counter);
        System.out.println(counter.join());
        long end = System.nanoTime();
        System.out.println(end - start);
    }

    public static class Counter extends RecursiveTask<Integer> {
        public static final int THRESHOLD = 1000;
        private double[] array;
        private int from;
        private int to;
        private DoublePredicate filter;

        int count = 0;

        public Counter(double[] array, int from, int to, DoublePredicate filter) {
            this.array = array;
            this.from = from;
            this.to = to;
            this.filter = filter;
        }

        @Override
        protected Integer compute() {
            if (to - from < THRESHOLD) {
                System.out.println(Thread.currentThread().getName() + " Begin Compute");
                for (int i = from; i < to; i++) {
                    if (filter.test(array[i])) {
                        count++;
                    }
                }
                return count;
            } else {
                System.out.println(Thread.currentThread().getName() + " Begin Fork");
                int mid = (from + to) / 2;
                Counter first = new Counter(array, from, mid, filter);
                Counter second = new Counter(array, mid, to, filter);
                first.fork();
                second.fork();
//            invokeAll(first, second);
                System.out.println(Thread.currentThread().getName() + " End Fork");
                int res = first.join() + second.join();
                System.out.println(Thread.currentThread().getName() + " get join");
                return res;
            }
        }
    }
}


